package com.ruoyi.patrol.service.impl;

import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.PatrolConstans;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.IsEmptyUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.patrol.domain.PtGuard;
import com.ruoyi.patrol.domain.PtProcessOpinion;
import com.ruoyi.patrol.domain.PtStaff;
import com.ruoyi.patrol.mapper.PtGuardMapper;
import com.ruoyi.patrol.service.IPtGuardService;
import com.ruoyi.patrol.service.IPtProcessOpinionService;
import com.ruoyi.patrol.utils.AreaCodeMapUtils;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.mapper.SysUserRoleMapper;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import io.jsonwebtoken.lang.Collections;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 安保人员Service业务层处理
 *
 * @author lkm
 * @date 2022-11-09
 */
@Service
public class PtGuardServiceImpl implements IPtGuardService {
    private static final Logger log = LoggerFactory.getLogger(PtStaffServiceImpl.class);
    @Autowired
    private PtGuardMapper ptGuardMapper;

    @Autowired
    private ProcessRuntime processRuntime;

    @Autowired
    private TaskRuntime taskRuntime;

    @Autowired
    private IPtProcessOpinionService ptProcessOpinionService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    /**
     * 查询安保人员
     *
     * @param id 安保人员ID
     * @return 安保人员
     */
    @Override
    public PtGuard selectPtGuardById(String id) {
        return ptGuardMapper.selectPtGuardById(id);
    }

    /**
     * 查询安保人员列表
     *
     * @param ptGuard 安保人员
     * @return 安保人员
     */
    @Override
    @DataScope(deptAlias = "s")
    public List<PtGuard> selectPtGuardList(PtGuard ptGuard) {
        List<PtGuard> ptGuards = ptGuardMapper.selectPtGuardList(ptGuard);
        addOpinion(ptGuards);
        return ptGuards;
    }

    @Override
    public List<PtGuard> selectPtGuardCheckList(PtGuard ptGuard) {
        List<PtGuard> ptGuards = ptGuardMapper.selectPtGuardCheckList(ptGuard);
        addOpinion(ptGuards);
        return ptGuards;
    }

    /**
     * 安保人员是否有排班
     *
     * @param id 安保人员ID
     * @return 结果
     */
    @Override
    public boolean isGuardOnSchedule(String id) {
        return ptGuardMapper.isGuardOnSchedule(id);
    }

    /**
     * 新增安保人员
     *
     * @param ptGuard 安保人员
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertPtGuard(PtGuard ptGuard) {
        String id = UUID.randomUUID().toString();
        ptGuard.setId(id);
        ptGuard.setCreateBy(SecurityUtils.getUsername());
        ptGuard.setCreateTime(DateUtils.getNowDate());
        ptGuard.setSchoolId(SecurityUtils.getSchoolId());
        // 审核通过后，为安保人员添加登录账号
        SysUser user = new SysUser();
        user.setUserName(ptGuard.getGuardPhonenumber());
        user.setNickName(ptGuard.getGuardName());
        user.setPhonenumber(ptGuard.getGuardPhonenumber());
        user.setSex(ptGuard.getGuardSex());
        // fixed elis  取出默认后6位密码改为 XYxc123456!@ 紧急修复先用硬编码 TODO
        user.setPassword(SecurityUtils.encryptPassword("XYxc123456!@"));
        user.setCreateBy(SecurityUtils.getUsername());
        user.setSchoolId(ptGuard.getSchoolId());
        user.setGuardId(ptGuard.getId());
        userService.insertUser(user);
        // 为安保人员添加角色
        SysRole role = roleService.selectRoleByRoleKey("guard");
        SysUserRole userRole = new SysUserRole();
        userRole.setRoleId(role.getRoleId());
        userRole.setUserId(user.getUserId());
        userRoleMapper.insertUserRole(userRole);
        return ptGuardMapper.insertPtGuard(ptGuard);
    }

    /**
     * 修改安保人员
     *
     * @param ptGuard 安保人员
     * @return 结果
     */
    @Override
    public int updatePtGuard(PtGuard ptGuard) {
        ptGuard.setUpdateTime(DateUtils.getNowDate());
        ptGuard.setUpdateBy(SecurityUtils.getUsername());
        int i = ptGuardMapper.updatePtGuard(ptGuard);
        // 更新账号信息
        SysUser user = userService.selectUserByGuardId(ptGuard.getId());
        user.setUserName(ptGuard.getGuardPhonenumber());
        user.setNickName(ptGuard.getGuardName());
        user.setPhonenumber(ptGuard.getGuardPhonenumber());
        user.setSex(ptGuard.getGuardSex());
        // 密码默认为电话号码后6位
        // fixed elis 修复在更新人员信息时会将密码重置问题
//        user.setPassword(SecurityUtils.encryptPassword(ptGuard.getGuardPhonenumber().substring(5)));
        user.setUpdateBy(SecurityUtils.getUsername());
        userService.updateUserMy(user);
        ptGuard.setUpdateTime(DateUtils.getNowDate());
        return i;
    }

    /**
     * 导入安保用户数据
     *
     * @param guardList       用户数据列表
     * @param isUpdateSupport 是否更新支持，如果已存在，则进行更新数据
     * @param operName        操作用户
     * @return 结果
     */
    @Override
    public String importGuard(List<PtGuard> guardList, Boolean isUpdateSupport, String operName) throws IOException {
        if (StringUtils.isNull(guardList) || guardList.size() == 0) {
            throw new CustomException("导入安保用户数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        //获取地区code map
        Map<String, String> map = AreaCodeMapUtils.getAreaCode();
        //遍历导入的数据集合
        for (int i = 0; i < guardList.size(); i++) {
            PtGuard guard = guardList.get(i);

            boolean is = IsEmptyUtils.isEmpty(guard.getGuardName(), guard.getGuardIdcard(), guard.getGuardCompany(), guard.getGuardPhonenumber(), guard.getGuardPoliticalExamine(), guard.getGuardPhysicalCondition());
            if (is) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、第 " + (i + 1) + " 条数据必填项不全");
                continue;
            }

            //验证身份证是否匹配
            String sIdCard = guard.getGuardIdcard();
            if (!StringUtils.isEmpty(sIdCard) && !Pattern.matches("^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[\\dXx]$", sIdCard)) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、第 " + (i + 1) + "条数据【身份证格式】错误");
                continue;
            }

            //验证手机号是否匹配
            String phoneNUm = guard.getGuardPhonenumber();
            if (!StringUtils.isEmpty(phoneNUm) && !Pattern.matches("^1[3-9]\\d{9}$", phoneNUm)) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、第 " + (i + 1) + "条数据【手机号格式】错误");
                continue;
            }

            try {
                // 验证是否存在这个用户
                //身份证验证
                PtGuard guardIdcard = ptGuardMapper.checkIdcardUnique(guard);
                //手机号验证
                PtGuard guardPhone = ptGuardMapper.checkPhoneUnique(guard);
                int checkUserNameUnique = userMapper.checkUserNameUnique(guard.getGuardPhonenumber());
                if (checkUserNameUnique > 0) {
                    failureNum++;
                    failureMsg.append("<br/>").append(failureNum).append("、第 ").append(i + 1).append("条数据【电话号码】已存在");
                    continue;
                }
                guard.setGuardSex("0".equals(guard.getGuardSex()) || "1".equals(guard.getGuardSex()) ? guard.getGuardSex() : "2");
                guard.setGuardNativePlace(map.get(guard.getGuardNativePlace()) == null ? "" : map.get(guard.getGuardNativePlace()));


                if (guardIdcard != null) {
                    guard.setId(guardIdcard.getId());
                }

                if (guardPhone != null) {
                    guard.setId(guardPhone.getId());
                }

                //不存在(添加用户)
                if (StringUtils.isNull(guardIdcard) && StringUtils.isNull(guardPhone)) {
                    insertPtGuard(guard);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、用户 " + guard.getGuardName() + " 导入成功");
                } else if (isUpdateSupport) {
                    if (guardIdcard != null && guardPhone != null && !guardIdcard.getId().equals(guardPhone.getId())) {
                        failureNum++;
                        failureMsg.append("<br/>" + failureNum + "、第 " + (i + 1) + "条数据更新失败 【身份证和联系电话】已存在");
                    } else {
                        guard.setUpdateBy(operName);
                        this.updatePtGuard(guard);
                        successNum++;
                        successMsg.append("<br/>" + successNum + "、用户 " + guard.getGuardName() + " 更新成功");
                    }
                } else {
                    failureNum++;
                    if (guardPhone != null) {
                        failureMsg.append("<br/>" + failureNum + "、第 " + (i + 1) + " 条数据【电话号码】已存在");
                    } else {
                        failureMsg.append("<br/>" + failureNum + "、第 " + (i + 1) + " 条数据【身份证号码】已存在");
                    }
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、第 " + (i + 1) + "条数据导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "成功数据：" + successNum + " 条!<br/>" + "失败数据：共 " + failureNum + " 条，失败原因如下：");
            throw new CustomException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }


    /**
     * 批量删除安保人员
     *
     * @param ids 需要删除的安保人员ID
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deletePtGuardByIds(String[] ids) {
        int i = ptGuardMapper.deletePtGuardByIds(ids);
        int j = userService.deleteUserByGuardIds(ids);
        return j;
    }

    /**
     * 删除安保人员信息
     *
     * @param id 安保人员ID
     * @return 结果
     */
    @Override
    public int deletePtGuardById(String id) {
        return ptGuardMapper.deletePtGuardById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int submitPtGuard(PtGuard ptGuard) {
        ptGuard.setStatus(PatrolConstans.GUARD_NOT_CHECK);
        if (StringUtils.isEmpty(ptGuard.getInstanceId())) { // 如果是新增的保安信息，需要开启流程实例
            ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder
                    .start()
                    .withProcessDefinitionKey("guard")
                    .withBusinessKey(ptGuard.getId())
                    .build());
            ptGuard.setInstanceId(processInstance.getId());

        }
        Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, Integer.MAX_VALUE));
        if (tasks != null && tasks.getTotalItems() > 0) {
            for (Task task : tasks.getContent()) {
                if (task.getProcessInstanceId().equals(ptGuard.getInstanceId())) {
                    if (task.getAssignee() == null) {
                        taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
                    }
                    taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId()).build());
                }
            }
        }
        int i = ptGuardMapper.updatePtGuard(ptGuard);
        return i;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int checkGuard(PtGuard ptGuard) {
        // 1. 添加流转意见
        PtProcessOpinion ptProcessOpinion = new PtProcessOpinion();
        ptProcessOpinion.setBusinessKey(ptGuard.getId());
        ptProcessOpinion.setOpinion(ptGuard.getOpinion());
        ptProcessOpinion.setIsAgree(ptGuard.getIsAgree());
        ptProcessOpinion.setTaskName(ptGuard.getTask().getName());
        ptProcessOpinion.setCreateBy(SecurityUtils.getUsername());
        ptProcessOpinion.setCreateTime(DateUtils.getNowDate());
        ptProcessOpinionService.insertPtProcessOpinion(ptProcessOpinion);
        // 2. 流程流转
        Task task = taskRuntime.task(ptGuard.getTask().getId());
        if (task != null) {
            if (task.getAssignee() == null) {
                taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
            }
            taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId()).withVariable("isAgree", ptGuard.getIsAgree()).build());
        }
        // 3. 更新guard表中的status
        if (ptGuard.getIsAgree() == 0) { // 同意
            // 首先校验手机号是否存在（sus_user表中）
            SysUser sysUser = userMapper.checkPhoneUnique(ptGuard.getGuardPhonenumber());
            if (!ObjectUtils.isEmpty(sysUser)) {
                throw new CustomException("审核安保'" + ptGuard.getGuardName() + "'失败，手机号码已存在");
            }
            ptGuard.setStatus(PatrolConstans.GUARD_PASS);
            // 审核通过后，为安保人员添加登录账号
            SysUser user = new SysUser();
            user.setUserName(ptGuard.getGuardPhonenumber());
            user.setNickName(ptGuard.getGuardName());
            user.setPhonenumber(ptGuard.getGuardPhonenumber());
            user.setSex(ptGuard.getGuardSex());
            // 密码默认为电话号码后6位
            user.setPassword(SecurityUtils.encryptPassword(ptGuard.getGuardPhonenumber().substring(5)));
            user.setCreateBy(SecurityUtils.getUsername());
            user.setSchoolId(ptGuard.getSchoolId());
            user.setGuardId(ptGuard.getId());
            userService.insertUser(user);
            // 为安保人员添加角色
            SysRole role = roleService.selectRoleByRoleKey("guard");
            SysUserRole userRole = new SysUserRole();
            userRole.setRoleId(role.getRoleId());
            userRole.setUserId(user.getUserId());
            userRoleMapper.insertUserRole(userRole);
        } else { // 退回
            ptGuard.setStatus(PatrolConstans.GUARD_REJECT);
        }
        int i = ptGuardMapper.updatePtGuard(ptGuard);
        return i;
    }

    @Override
    public String checkPhoneUnique(PtGuard ptGuard) {
        if (!StringUtils.isEmpty(ptGuard.getId())) { // 表明是修改
            PtGuard guard = ptGuardMapper.selectPtGuardById(ptGuard.getId());
            if (guard.getGuardPhonenumber().equals(ptGuard.getGuardPhonenumber())) { // 如果前端传过来的电话和后端的一样，表明没有修改
                return PatrolConstans.UNIQUE;
            }
        }
        SysUser user = userMapper.checkPhoneUnique(ptGuard.getGuardPhonenumber());
        if (ObjectUtils.isEmpty(user)) {
            return PatrolConstans.UNIQUE;
        }
        return PatrolConstans.NOT_UNIQUE;
    }

    @Override
    public String checkIdcardUnique(PtGuard ptGuard) {
        if (!StringUtils.isEmpty(ptGuard.getId())) { // 表明是修改
            PtGuard guard = ptGuardMapper.selectPtGuardById(ptGuard.getId());
            if (guard.getGuardIdcard().equals(ptGuard.getGuardIdcard())) { // 如果前端传过来的身份证和后端的一样，表明没有修改
                return PatrolConstans.UNIQUE;
            }
        }
        PtGuard guard = ptGuardMapper.checkIdcardUnique(ptGuard);
        if (ObjectUtils.isEmpty(guard)) {
            return PatrolConstans.UNIQUE;
        }
        return PatrolConstans.NOT_UNIQUE;
    }

    @Override
    public int selectGuardCount(Long schoolId) {
        return ptGuardMapper.selectGuardCount(schoolId);
    }

    @Override
    public List<PtGuard> selectPtGuardNoCheckList() {
        return ptGuardMapper.selectPtGuardNoCheckList();
    }

    @Override
    public List<PtGuard> selectPtGuardNoSubmitList(Long schoolId) {
        return ptGuardMapper.selectPtGuardNoSubmitList(schoolId);
    }

    private void addOpinion(List<PtGuard> ptGuards) {
        for (PtGuard guard : ptGuards) {
            List<PtProcessOpinion> ptProcessOpinions = guard.getPtProcessOpinions();
            if (!Collections.isEmpty(ptProcessOpinions)) {
                ptProcessOpinions.sort(new Comparator<PtProcessOpinion>() {
                    @Override
                    public int compare(PtProcessOpinion o1, PtProcessOpinion o2) {
                        long l = o2.getCreateTime().getTime() - o1.getCreateTime().getTime();
                        return l > 0 ? 1 : -1;
                    }
                });
                guard.setPtProcessOpinion(ptProcessOpinions.get(0));
            }
        }
    }

}
